<template>
  <div class="graph-right-config">
    <a-form
      :model="formModel"
      ref="formRef"
      layout="vertical"
      size="small"
      show-colon
    >
      <a-form-item field="name" label="名称" hide-asterisk show-colon>
        <a-input
          :disabled="allDisabled"
          :max-length="20"
          allow-clear
          show-word-limit
          v-model="formModel.name"
          placeholder="请输入"
          @blur="nameBlur"
        />
      </a-form-item>
      <a-form-item
        field="graphType"
        label="类型"
        show-colon
        class="graphtype-form-item"
      >
        <AGraphTypeRadio
          :disabled="allDisabled"
          :types="['NUMBER', 'BAR', 'AREA', 'PIE', 'GAUGE']"
          v-model="formModel.graphType"
          @change="typeChange"
        />
      </a-form-item>
      <a-form-item field="metricsName" class="metric-form-item">
        <template #label>
          <a-row
            @click.prevent="() => {}"
            justify="space-between"
            align="center"
          >
            <span>指标 :</span>
            <a-popover
              position="lt"
              trigger="click"
              :content-style="{ width: '210px', padding: '0' }"
              v-model:popup-visible="indexPopoverVisible"
              content-class="init-add-card-content"
            >
              <a-button
                type="text"
                :disabled="allDisabled"
                @click="indexPopoverVisible = true"
              >
                <template #icon><IconSwap :size="14" /></template>
              </a-button>
              <template #content>
                <MetricTree @node-click="nodeClick" height="450px" />
              </template>
            </a-popover>
          </a-row>
        </template>
        <a-input
          v-if="!allDisabled"
          :model-value="formModel.metricsSetting.metricsName"
          placeholder="请选择"
          readonly
        >
          <template #suffix>
            <IconSettings @click="metricDetailSetting" style="color: #9b9fab" />
          </template>
        </a-input>
      </a-form-item>
      <a-form-item
        v-if="formModel.type === GraphType.AREA"
        field="timeFrequency.offset"
        :rules="[{ required: true, message: 'x轴（时间频率）不能为空' }]"
        validate-trigger="change"
        label="x轴（时间频率）"
        show-colon
      >
        <div class="time-content">
          <span class="nowrap needmr">最近</span>
          <a-input-number
            :style="{ flex: 1 }"
            v-model="formModel.timeFrequency.offset"
            :disabled="allDisabled"
            placeholder="请输入"
            :min="1"
            :precision="0"
          />
          <span class="nowrap">{{ currentTimeLabel }}</span>
        </div>
      </a-form-item>
      <a-form-item
        v-if="formModel.type !== GraphType.AREA"
        label="默认数据时间"
        class="form-item-default-time"
        content-class="form-item-default-time-content"
        required
        show-colon
      >
        <a-form-item hide-label hide-asterisk>
          <a-select
            v-model="formModel.dateCondition.dateMode"
            :disabled="allDisabled"
            :options="defaultTimeTypeList"
            placeholder="请选择"
            :style="{ marginRight: '6px' }"
          >
            <template #arrow-icon>
              <IconCaretDown size="12" />
            </template>
          </a-select>
        </a-form-item>
        <a-form-item
          v-if="formModel.dateCondition.dateMode === DefaultTimeType.BEFORE"
          field="dateCondition.offset"
          :rules="[
            {
              required: true,
              message: '请填写默认数据时间'
            }
          ]"
          validate-trigger="change"
          hide-label
          hide-asterisk
        >
          <a-input-number
            v-model="formModel.dateCondition.offset"
            :disabled="allDisabled"
            placeholder="请输入"
            :min="1"
            :style="{ marginRight: '6px' }"
            :precision="0"
          />
          <span style="white-space: nowrap">{{ currentTimeLabel }}</span>
        </a-form-item>
        <a-form-item
          v-if="formModel.dateCondition.dateMode === DefaultTimeType.FIXED"
          field="dateCondition.fixDate"
          :rules="[
            {
              required: true,
              message: '请选择默认数据时间'
            }
          ]"
          validate-trigger="change"
          hide-label
          hide-asterisk
        >
          <component
            :is="getCurrentTimeComponent(currentTimeframe!)"
            v-model="formModel.dateCondition.fixDate"
            :disabled="allDisabled"
          ></component>
        </a-form-item>
      </a-form-item>
      <a-form-item
        v-if="
          formModel.type === GraphType.BAR || formModel.type === GraphType.PIE
        "
        field="distributeDimId"
        label="分布维度"
        show-colon
      >
        <a-select
          v-model="formModel.distributeDimId"
          :disabled="allDisabled"
          :options="dimensionOptions"
          :field-names="{ label: 'columnDimName', value: 'dimensionId' }"
          @change="distributeDimChange"
          allow-clear
          placeholder="请选择"
        >
          <template #arrow-icon>
            <IconCaretDown size="12" />
          </template>
        </a-select>
      </a-form-item>
      <template v-if="formModel.type === GraphType.GAUGE">
        <a-form-item field="targetVal" label="目标值" show-colon>
          <a-input-number
            v-model.number="formModel.targetVal"
            :disabled="allDisabled"
            placeholder="请输入"
            :min="1"
            :precision="0"
          />
        </a-form-item>
        <!-- <a-form-item
          :rules="[
            {
              validator: phaseTargetValValidator
            }
          ]"
          field="phaseTargetVal"
          label="阶段目标值"
          show-colon
        >
          <a-input-number
            v-model.number="formModel.phaseTargetVal"
            :disabled="allDisabled"
            placeholder="请输入"
            :min="1"
            :precision="0"
          />
        </a-form-item> -->
        <a-form-item
          :merge-props="false"
          :content-flex="false"
          class="progesstrack-form-item"
          content-class="progesstrack-content-item"
        >
          <template #label>
            <a-row
              @click.prevent="() => {}"
              justify="space-between"
              align="center"
            >
              <span>时间进度跟踪 :</span>
              <a-switch v-model="formModel.progessTrack.enabled" size="small" />
            </a-row>
          </template>
          <template v-if="formModel.progessTrack.enabled">
            <a-form-item
              :field="
                formModel.progessTrack.enabled ? 'progessTrack.startDate' : ''
              "
              class="progesstrack-time-item"
              :rules="[{ required: true, message: '请选择开始跟踪时间' }]"
              validate-trigger="change"
              required
              label="开始"
              show-colon
            >
              <component
                :is="getCurrentTimeComponent(currentTimeframe!)"
                v-model="formModel.progessTrack.startDate"
              ></component>
            </a-form-item>
            <a-form-item
              :field="
                formModel.progessTrack.enabled ? 'progessTrack.endDate' : ''
              "
              class="progesstrack-time-item"
              :rules="[
                {
                  required: true,
                  validator: endDateValidator
                }
              ]"
              label="结束"
              show-colon
            >
              <component
                :is="getCurrentTimeComponent(currentTimeframe!)"
                v-model="formModel.progessTrack.endDate"
              ></component>
            </a-form-item>
          </template>
        </a-form-item>
      </template>

      <a-form-item field="_metricContrast" class="compare-form-item">
        <template #label>
          <a-row
            @click.prevent="() => {}"
            justify="space-between"
            align="center"
          >
            <span>指标对比 :</span>
            <a-button
              type="text"
              :disabled="allDisabled || formModel.compares.length === 2"
              @click="addCompare"
            >
              <template #icon><IconPlus :size="14" /></template>
            </a-button>
          </a-row>
        </template>
        <a-space direction="vertical" fill :size="6" style="width: 100%">
          <template
            v-for="(item, index) in formModel.compares"
            :key="item.compareName"
          >
            <a-input
              v-model="item.compareName"
              placeholder="请选择"
              readonly
              @click="comparesItemClick($event, item, index)"
            >
              <template #suffix>
                <IconDelete
                  @click="deleteCompare(index)"
                  style="color: #9b9fab"
                />
              </template>
            </a-input>
          </template>
        </a-space>
      </a-form-item>
      <a-form-item>
        <a-button
          :loading="confirmLoading"
          @click="confirmConfig('confirm')"
          :disabled="allDisabled"
          long
          type="outline"
          >确定</a-button
        >
      </a-form-item>
    </a-form>
  </div>
  <MetricDetailSettingModal
    v-if="formModel.metricsSetting.metricsId"
    v-model="metricDetailVisible"
    v-model:data="formModel.metricsSetting"
    :key="formModel.metricsSetting.metricsId"
  />
  <MetricCompareModal
    v-model="compareVisilble"
    :data="comparesData"
    @ok="confirmCompare"
  />
</template>

<script lang="ts" setup>
import { ref, reactive, watchEffect, inject, computed, Ref, watch } from 'vue';
import {
  IconSwap,
  IconSettings,
  IconPlus,
  IconDelete,
  IconCaretDown
} from '@arco-design/web-vue/es/icon';
import { AGraphTypeRadio } from '@dangojs/a-graph-card';
import MetricDetailSettingModal from './metricDetailSettingModal.vue';
import MetricCompareModal from './metricCompareModal.vue';
import MetricTree from '../graphLeftTree/index.vue';
import API from '@/services';
import { cloneDeep } from 'lodash';
import {
  statisticalPeriodUnitOption,
  GraphType,
  defaultGlobalModel,
  getDefaultConfigModel,
  TimeFrameType
} from '../../type';
import { getCurrentTimeComponent, quarterTimeFormater } from '../../hooks';
import { Message } from '@arco-design/web-vue';
enum DefaultTimeType {
  BEFORE = 'BEFORE',
  TODAY = 'TODAY',
  FIXED = 'FIXDATE'
}

const props = withDefaults(
  defineProps<{
    cardData: Record<string, any> | null;
  }>(),
  {
    cardData: null
  }
);

const emits = defineEmits(['optionChange']);

const currentTimeframe = inject<Ref>('current-timeframe');
const updateCurrentTimeframe = inject<(val: string) => void>(
  'update-current-timeframe'
);
const updateMinTimeframe = inject<(val: string) => void>(
  'update-min-timeframe'
);
const currentTimeLabel = computed(() => {
  return (
    (
      statisticalPeriodUnitOption.find(
        (item) => item.value === currentTimeframe!.value
      ) || {}
    ).label || '日'
  );
});

const formRef = ref();
const metricDetailVisible = ref(false);
const compareVisilble = ref(false);
const indexPopoverVisible = ref(false);
const comparesData = ref();
let comparesIndex = -1;
const confirmLoading = ref(false);
const formModel = reactive<Record<string, any>>({
  name: '',
  graphSize: 'SMALL',
  graphType: null,
  metricsSetting: {
    metricsId: null,
    metricsName: '',
    metricsConditions: []
  },
  dataTime: '',
  dateCondition: {
    dateMode: DefaultTimeType.BEFORE,
    offset: 1,
    fixDate: '',
    timeUnit: 'day'
  },
  compares: [],
  timeFrequency: {
    offset: 1,
    timeUnit: 'day'
  },
  distributeDimId: undefined,
  distributeDimName: undefined,
  targetVal: undefined,
  phaseTargetVal: undefined,
  progessTrack: {
    enabled: true,
    startDate: '',
    endDate: '',
    timeUnit: 'day'
  },
  result: {},
  type: GraphType.NUMBER
});
const allDisabled = ref(true);
const defaultTimeTypeList = reactive([
  { label: '之前', value: DefaultTimeType.BEFORE },
  { label: '当日', value: DefaultTimeType.TODAY },
  { label: '固定日期', value: DefaultTimeType.FIXED }
]);

const endDateValidator = (value: any, cb: any) => {
  if (!value) {
    cb('请选择结束跟踪时间');
  } else if (
    formModel.progessTrack.startDate &&
    new Date(value).getTime() <
      new Date(formModel.progessTrack.startDate).getTime()
  ) {
    cb('结束时间需大于开始时间');
  }
};
const phaseTargetValValidator = (value: any, cb: any) => {
  if (value && value > (formModel.targetVal || 0)) {
    cb('阶段目标值需小于目标值');
  }
};

// 切换卡片类型(更新所有时间粒度)
const typeChange = async (item: any) => {
  formModel.graphSize = item.defaultSize;
  formModel.graphType = item.type;
  formModel.type = GraphType[item.type];
  let cardConfig = cloneDeep(getDefaultConfigModel(formModel.type));
  updateAllTimeUnit(currentTimeframe!.value);
  if (formModel.type === GraphType.AREA) {
    formModel.timeFrequency.offset = cardConfig.timeFrequency.offset;
  }
  Object.keys(cardConfig).forEach((key) => {
    cardConfig[key] = cloneDeep(formModel[key]);
  });
  // 处理季度时间格式
  quarterTimeFormater(cardConfig, TimeFrameType.QUARTER);
  let params: any = {
    boardConfig: defaultGlobalModel,
    card: {
      cardConfig,
      name: formModel.name
    }
  };
  delete params.card.cardConfig.result;
  const { code, data, msg } =
    await API.metricsBoard.postMetricsBoardCardPreview(params);
  if (code === 200) {
    formModel.result = (data!.cardConfig as any).result;
  } else {
    Message.error(msg);
  }
  emits('optionChange', formModel, 'typeChange');
};

watch(
  () => props.cardData,
  (val, oldVal) => {
    formRef.value.clearValidate();
    if (val) {
      allDisabled.value = false;
      Object.keys(formModel).forEach((key) => {
        formModel[key] = val[key] ?? val.cardConfig[key] ?? formModel[key];
        if (key === 'targetVal' || key === 'phaseTargetVal') {
          formModel[key] = +formModel[key];
        }
      });
      // 处理季度时间格式
      quarterTimeFormater(formModel, TimeFrameType.MONTH);
      // 图表切换重新获取分布维度下拉，更新时间粒度
      if (
        !oldVal ||
        val.cardConfig.metricsSetting.metricsId !==
          oldVal.cardConfig.metricsSetting.metricsId
      ) {
        let timeUnit = val.cardConfig.metricsSetting.statisticalPeriod.timeUnit;
        getDimensionById();
        updateMinTimeframe!(timeUnit);
        updateCurrentTimeframe!(timeUnit);
      }
    } else {
      allDisabled.value = true;
    }
  }
);
// 图表名称失去焦点（为空回退原名称）
const nameBlur = () => {
  !formModel.name && (formModel.name = props.cardData!.name);
  emits('optionChange', formModel, 'nameChange');
};
const metricDetailSetting = () => {
  if (!formModel.metricsSetting.metricsId) return;
  metricDetailVisible.value = true;
};

// 指标切换，重新获取分布维度下拉，并更新时间粒度
const nodeClick = async (keys: any, item: any) => {
  indexPopoverVisible.value = false;
  if (formModel.metricsSetting.metricsId === keys[0]) {
    return;
  }
  const { code, data, msg } =
    await API.metricsModelRelation.getGetMetricsFilterById({ id: keys[0] });
  if (code === 200) {
    if (data && data.timeframe) {
      await getDimensionById(keys[0]);
      confirmConfig('metricsChange').then(() => {
        updateMinTimeframe!(data.timeframe!);
        updateCurrentTimeframe!(data.timeframe!);
        formModel.metricsSetting.metricsId = keys[0];
        formModel.name = formModel.metricsSetting.metricsName = item.name;
        // 清空过滤条件
        formModel.metricsSetting.metricsConditions = [];
        emits('optionChange', formModel, 'metricsChange');
      });
    } else {
      Message.error('当前指标无开发逻辑，无法使用');
    }
  } else {
    Message.error(msg);
  }
};
const addCompare = () => {
  comparesData.value = null;
  comparesIndex = -1;
  compareVisilble.value = true;
};
const deleteCompare = (index: number) => {
  formModel.compares.splice(index, 1);
};
const confirmCompare = (data: any) => {
  if (comparesIndex > -1) {
    formModel.compares.splice(comparesIndex, 1, cloneDeep(data));
  } else {
    formModel.compares.push(cloneDeep(data));
  }
};
const distributeDimChange = () => {
  formModel.distributeDimName = (
    dimensionOptions.value.find(
      (item) => item.dimensionId === formModel.distributeDimId
    ) || {}
  ).columnDimName;
};

// 获取分布维度下拉
const dimensionOptions = ref<any[]>([]);
const getDimensionById = async (mid?: number) => {
  let id = mid || formModel.metricsSetting.metricsId;
  if (!id) return;
  const { code, data = {} } =
    await API.metricsModelRelation.getGetMetricsFilterById({ id });
  if (code === 200) {
    dimensionOptions.value = (data.queryFieldList || []).filter(
      (item) => item.dimensionId && item.columnType === 2
    );
    if (dimensionOptions.value.length) {
      formModel.distributeDimId = dimensionOptions.value[0].dimensionId;
      distributeDimChange();
    }
  }
};

const comparesItemClick = (e: MouseEvent, item: any, index: number) => {
  comparesData.value = null;
  const tar = e.target as HTMLElement;
  if (tar.nodeName !== 'INPUT') return;
  comparesData.value = item;
  compareVisilble.value = true;
  comparesIndex = index;
};
// 点击确定（成功获取数据后派发optionChange事件，并更新所有timeUnit）
const confirmConfig = async (type: string) => {
  const validateRes = await formRef.value.validate();
  if (validateRes) {
    return;
  }
  updateAllTimeUnit(currentTimeframe!.value);
  let cardConfig = cloneDeep(getDefaultConfigModel(formModel.type));
  Object.keys(cardConfig).forEach((key) => {
    cardConfig[key] = cloneDeep(formModel[key]);
  });
  // 处理季度时间格式
  quarterTimeFormater(cardConfig, TimeFrameType.QUARTER);
  let params = {
    boardConfig: defaultGlobalModel,
    card: {
      cardConfig,
      name: formModel.name
    }
  };
  delete params.card.cardConfig.result;
  confirmLoading.value = true;
  try {
    const {
      code,
      data = {},
      msg
    } = await API.metricsBoard.postMetricsBoardCardPreview(params as any);
    if (code === 200) {
      formModel.result = (data.cardConfig as any).result;
      type === 'confirm' && emits('optionChange', formModel, 'confirm');
      confirmLoading.value = false;
      Message.success(type === 'metricsChange' ? '指标切换成功' : '预览成功');
    } else {
      Message.error(msg);
      confirmLoading.value = false;
    }
  } catch (error) {
    confirmLoading.value = false;
  }
};

const updateAllTimeUnit = (t: string) => {
  formModel.metricsSetting.statisticalPeriod.timeUnit = t;
  formModel.dateCondition.timeUnit = t;
  formModel.timeFrequency.timeUnit = t;
  formModel.progessTrack.timeUnit = t;
  formModel.compares.forEach((item: any) => {
    item.dateCondition.timeUnit = t;
  });
};
</script>

<style lang="scss" scoped>
.graph-right-config {
  padding: 10px 0;
  height: 100%;
  overflow: auto;
  background-color: var(--color-bg-1);
  .nowrap {
    white-space: nowrap;
  }
}
</style>
<style lang="scss">
.graph-right-config {
  .arco-input-wrapper.arco-input-disabled,
  .arco-select-view-single.arco-select-view-disabled {
    background-color: #f6f8fc;
    border-color: #d4d7e1;
    color: #9b9fab;
  }
  .arco-form-item {
    margin-bottom: 18px;
    padding-left: 18px;
    padding-right: 18px;
    box-sizing: border-box;
  }
  .arco-form-item-layout-vertical > .arco-form-item-label-col {
    margin-bottom: 6px;
    line-height: 22px;
  }
  .arco-form-item-label-col > .arco-form-item-label {
    color: var(--color-text-1);
  }
  .graphtype-form-item {
    padding-bottom: 10px;
    border-bottom: 9px solid #f6f8fc;
  }
  .metric-form-item {
    .arco-form-item-label {
      width: 100%;
    }
    .arco-form-item-wrapper-col {
      min-height: 0;
    }
    .arco-form-item-content {
      min-height: 0;
      background: #f6f8fc;
      border-radius: 3px;
      padding: v-bind('!allDisabled?"6px":0');
    }
    .arco-input-suffix {
      cursor: pointer;
    }
  }
  .progesstrack-form-item {
    .arco-form-item-label {
      width: 100%;
    }
    .arco-form-item-wrapper-col {
      min-height: 0;
    }
    .arco-form-item-content {
      min-height: 0;
    }
    .progesstrack-content-item {
      flex-direction: column;
      .arco-picker {
        width: 100%;
      }
    }
    .progesstrack-time-item {
      display: flex;
      .arco-form-item-label-col {
        margin: 4px 10px 0 0;
      }
    }
  }
  .compare-form-item {
    .arco-form-item-label {
      width: 100%;
    }
    .arco-form-item-wrapper-col {
      min-height: 0;
    }
    .arco-form-item-content {
      min-height: 0;
      background: #f6f8fc;
      border-radius: 3px;
      padding: v-bind('formModel.compares.length?"6px":0');
    }
    .arco-input-suffix {
      cursor: pointer;
    }
  }
  .time-content {
    display: flex;
    align-items: center;
    width: 100%;
    & > .needmr {
      margin-right: 6px;
    }
    & > .arco-picker {
      flex-grow: 1;
    }
    & > .arco-input-number {
      flex-grow: 1;
      margin-right: 6px;
    }
  }
  .form-item-default-time {
    margin-bottom: 0;
    .form-item-default-time-content {
      align-items: flex-start;
    }
    .arco-form-item {
      padding: 0;
    }
  }
  .arco-input-number-mode-embed .arco-input-number-step {
    opacity: 1;
  }
}
</style>
